/* 
 * File:   secd.h
 * Author: Administrator
 *
 * Created on 2016年9月23日, 下午2:08
 */

#ifndef SECD_H
#define SECD_H

#include<stack>
#include<list>
#include<map>
#include<vector>
#include<string>

#ifdef __cplusplus




extern "C" {
#endif
    typedef void (*ins_func)(void *vm);
    typedef void (*c_func)(void *vm, std::vector<void*>* args);

    typedef enum ValueTypes {
        varNil,
        varString,
        varInt,
        varFloat,
        varFunc,
        varLambda,
        varBool,
        varList,
        varChar,
        varSymbol,
        varName,
        varDict
    } ValueTypes;

    typedef struct ValueStuct {
        ValueTypes type;

        union {
            char *strValue;
            long intValue;
            float floatValue;
            char charValue;
            int funcValue; //code list
            c_func cfuncValue; //c func pointer
            std::vector<struct ValueStuct *> *listValue;
        } value;
        int length;
        std::vector<void*> *Env;
    } Value;

    typedef struct {
        std::vector<void*> *environment;
        int stack;
        int IP;
    } DumpItem;

    //    struct SecdVm {
    //        void *code;
    //        void* globalEnv;
    //        void*environment;
    //        void *stack;
    //        void *dump;
    //        void* instructions[512];
    //        int IP;
    //    };

    typedef enum Instruction {
        I_add = 0x01,
        I_sub = 0x02,
        I_div = 0x03,
        I_mul = 0x04,
        I_mod = 0x05,
        I_ld = 0x06,
        I_ldi = 0x07,
        I_ldd = 0x08,
        I_lds = 0x09,
        I_ldc = 0x0a,
        I_ldsy = 0x0b, //symbol
        I_ldb = 0x0c, //bool
        I_ldv = 0x0d, //var name
        I_ldf = 0x0e,
        I_ap = 0x0f,
        I_rtn = 0x10,
        I_nil = 0x11,
        I_cons = 0x12,
        I_sel = 0x13,
        I_join = 0x14,
        I_eq = 0x15,
        I_gt = 0x16,
        I_lt = 0x17,
        I_ge = 0x18,
        I_le = 0x19,
        I_def = 0x1a,
        I_stop = 0x1b,
        I_ldn = 0x1c,
        I_ldfn = 0x1d,
        I_dum = 0x1e,
        I_rap = 0x1f,
        I_rec = 0x20,
        I_tap = 0x21
    } Instruction;

    class SecdVm {
    public:
        char *code;
        std::map<std::string, Value*> *globalEnv;
        std::vector<void*> *environment;
        std::stack<Value*> *stack;
        std::stack<DumpItem*> *dump;
        ins_func instructions[512];
        int IP;
        SecdVm();
        void regist_instruction(short instruction, ins_func func);
        void regist_global_val(char* name, c_func func);
        Value* lookup_global(char* name);
        Value* lookup_local(int level, int position);
        void load_binary(char *code, long len);
        int parse_binary(char *code, int len);
        void run();
        ~SecdVm();
    };


    //    void regist_opcode(struct SecdVm *vm, short opcode, ins_func func);
    //    void regist_global_func(struct SecdVm *vm, char *name, c_func func);
    //    Value* lookup_global(struct SecdVm *vm, char *name);
    //    Value* lookup_local(struct SecdVm *vm, int level, int position);
    //    void SecdVm_init(struct SecdVm *vm);
    //    void SecdVm_run(struct SecdVm *vm);

    Value* make_integer(int n);

    Value* make_float(float n);

    Value* make_cfunc(c_func n);

    Value* make_lambda(int n);

    Value* make_char(char n);

    Value* make_bool(int n);

    Value* make_nil();
    Value* make_dict();

    Value* make_symbol(char *n, int len);

    Value* make_list(std::vector<void*> *n);

    Value* make_string(char *n, int len);
    Value* make_name(char *n, int len);

    int is_integer(Value* v);

    int is_char(Value* v);

    int is_string(Value* v);

    int is_symbol(Value* v);

    int is_float(Value* v);
    int is_list(Value* v);

    int is_lambda(Value* v);
    int is_name(Value* v);
    int is_dict(Value* v);

    int is_cfunc(Value* v);

    int is_nil(Value* v);

    int is_bool(Value* v);

    int int_value(Value* v);

    float float_value(Value* v);

    char* string_value(Value* v);
    char* name_value(Value* v);

    char char_value(Value* v);

    int bool_value(Value* v);

    char* symbol_value(Value* v);

    c_func cfunc_value(Value* v);

    int lambda_value(Value* v);

    std::vector<Value*>* list_value(Value* v);
#ifdef __cplusplus
}
#endif


#endif /* SECD_H */

